//
//  DemoMultiThread.swift
//  swiftDemo
//
//  Created by JIENING ZHANG on 2022/12/5.
//  Copyright © 2022 lovivid. All rights reserved.
//

import UIKit

class DemoMultiThread: NSObject {
    class func taskA(_ info:String) {
        print ("taskA begin : \(info), Thread.current = \(Thread.current)");
        let opTimeInMs = arc4random_uniform(501);
        Thread.sleep(forTimeInterval:Double(opTimeInMs)/1000.0);
        print ("taskA end \(opTimeInMs)ms: \(info)");
    }
    
    class func taskB(_ info:String) {
        print ("taskB begin : \(info), Thread.current = \(Thread.current)");
        let opTimeInMs = arc4random_uniform(501);
        Thread.sleep(forTimeInterval:Double(opTimeInMs)/1000.0);
        print ("taskB end \(opTimeInMs)ms: \(info)");
    }
    
    class func taskC(_ info:String) {
        print ("taskC begin : \(info), Thread.current = \(Thread.current)");
        let opTimeInMs = arc4random_uniform(501);
        Thread.sleep(forTimeInterval:Double(opTimeInMs)/1000.0);
        print ("taskC end \(opTimeInMs)ms: \(info)");
    }
    
    class func taskD(_ info:String) {
        print ("taskD begin : \(info), Thread.current = \(Thread.current)");
        let opTimeInMs = arc4random_uniform(501);
        Thread.sleep(forTimeInterval:Double(opTimeInMs)/1000.0);
        print ("taskD end \(opTimeInMs)ms: \(info)");
    }
    
    
    class func run4TaskByThreadAndLock() {
        // 4个任务ABCD
        // C依赖AB完成，使用 NSThread NSLock 实现
        // D和ABC无关，期望尽量快执行完成所有任务
        
        let lockA = NSLock();
        lockA.lock();
        let tA = Thread {
            taskA("ThreadAndLock")
            lockA.unlock();
        };
        
        let lockB = NSLock();
        lockB.lock();
        let tB = Thread {
            taskB("ThreadAndLock");
            lockB.unlock();
        };
        
        let tC = Thread {
            lockA.lock();
            lockB.lock();
            taskC("ThreadAndLock");
            lockB.unlock();
            lockA.unlock();
        };
        
        let tD = Thread {
            taskD("ThreadAndLock");
        };
        
        tA.start();
        tB.start();
        tC.start();
        tD.start();
    }
    
    class func run4TaskByThreadAndSemaphore() {
        // 4个任务ABCD
        // C依赖AB完成，使用 NSThread NSLock 实现
        // D和ABC无关，期望尽量快执行完成所有任务
        // 使用 Thread 和 信号量 实现
        
        let semA = DispatchSemaphore(value: 0); //
        let tA = Thread {
            taskA("ThreadAndSemaphore");
            semA.signal();
        };
        
        let semB = DispatchSemaphore(value: 0); //
        let tB = Thread {
            taskB("ThreadAndSemaphore");
            semB.signal();
        };
        
        let tC = Thread {
            semA.wait();    // taskC 等到两个信号量都满足才开始执行
            semB.wait();
            taskC("ThreadAndSemaphore");
        };
        
        let tD = Thread {
            taskD("ThreadAndSemaphore");
        };
        
        tA.start();
        tB.start();
        tC.start();
        tD.start();
    }
    
    class func run4TaskByOperation() {
        // 4个任务ABCD
        // C依赖AB完成，使用 NSThread NSLock 实现
        // D和ABC无关，期望尽量快执行完成所有任务
        // 使用 Operation 和 OperationQueue 实现
        
        let opA = BlockOperation {
            taskA("Operation");
        }
        
        let opB = BlockOperation {
            taskB("Operation");
        }
        
        let opC = BlockOperation {
            taskC("Operation");
        }
        opC.addDependency(opA);
        opC.addDependency(opB);
        
        let opD = BlockOperation {
            taskD("Operation");
        }
        
        let queue = OperationQueue();
        queue.addOperation(opA);
        queue.addOperation(opB);
        queue.addOperation(opC);
        queue.addOperation(opD);
    }
    
    class func run4TaskByGCD() {
        // 4个任务ABCD
        // C依赖AB完成，使用 NSThread NSLock 实现
        // D和ABC无关，期望尽量快执行完成所有任务
        // 使用 GCD 和 Lock 实现
        
        let lockA = NSLock();
        lockA.lock();
        DispatchQueue.global().async {
            taskA("run4TaskByGCD");
            lockA.unlock();
        }
        
        let lockB = NSLock();
        lockB.lock();
        DispatchQueue.global().async {
            taskB("run4TaskByGCD");
            lockB.unlock();
        }
        
        DispatchQueue.global().async {
            lockA.lock();
            lockB.lock();
            taskC("run4TaskByGCD");
            lockB.unlock();
            lockA.unlock();
        }
        
        DispatchQueue.global().async {
            taskD("run4TaskByGCD");
        }
    }
    
    class func demoLogic() {
        //run4TaskByThreadAndLock();
        run4TaskByThreadAndSemaphore();
        
        //run4TaskByOperation();
        
        //run4TaskByGCD();
    }
}
